package edu.cgpi.core.entidade;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import com.thoughtworks.xstream.annotations.XStreamImplicit;

public class Reta implements FormaGeometrica {

	@XStreamImplicit
	private Ponto[] pontos = new Ponto[2];

	public Reta(Ponto ponto1, Ponto ponto2) {
		this.pontos[0] = ponto1;
		this.pontos[1] = ponto2;
	}

	public Ponto getPonto1() {
		return this.pontos[0];
	}

	public void setPonto1(Ponto ponto1) {
		this.pontos[0] = ponto1;
	}

	public Ponto getPonto2() {
		return this.pontos[1];
	}

	public void setPonto2(Ponto ponto2) {
		this.pontos[1] = ponto2;
	}

	public Ponto obterLocalizacao() {
		return this.pontos[0];
	}

	/**
	 * Obtém todos os pontos desta Reta.
	 * O algorítmo verifica a diferença entre as abscissas e
	 * as coordenadas dos pontos para decidir qual iteração será feita.
	 */
	public Set<Ponto> obterPontos() {
		Double deltaX = Math.abs(this.pontos[0].getX() - this.pontos[1].getX());
		Double deltaY = Math.abs(this.pontos[0].getY() - this.pontos[1].getY());
		if (deltaX >= deltaY) {
			return obterPontosEixoX();
		} else {
			return obterPontosEixoY();
		}
	}

	private Double calcularCoeficienteAngular() {
		double deltaY = this.pontos[0].getY() - this.pontos[1].getY();
		double deltaX = this.pontos[0].getX() - this.pontos[1].getX();
		return deltaY / deltaX;
	}

	
	private Double calcularCoeficienteLinear() {
		return this.pontos[0].getY() - calcularCoeficienteAngular() * this.pontos[0].getX();
	}

	/**
	 * Obtém os pontos desta Reta a partir da iteração pelo eixo x.
	 */
	private Set<Ponto> obterPontosEixoX() {
		int menor = (int) Math.min(this.pontos[0].getX(), this.pontos[1].getX());
		int maior = (int) Math.max(this.pontos[0].getX(), this.pontos[1].getX());
		Set<Ponto> pontos = new HashSet<Ponto>();
		for (int x = menor; x <= maior; x++) {
			Integer y = (int) Math.round(calcularCoeficienteAngular() * x + calcularCoeficienteLinear());
			pontos.add(new Ponto((double) x, (double) y));
		}
		return pontos;
	}

	/**
	 * Obtém os pontos desta Reta a partir da iteração pelo eixo y.
	 */
	private Set<Ponto> obterPontosEixoY() {
		int menor = (int) Math.min(this.pontos[0].getY(), this.pontos[1].getY());
		int maior = (int) Math.max(this.pontos[0].getY(), this.pontos[1].getY());
		Set<Ponto> pontos = new HashSet<Ponto>();
		for (int y = menor; y <= maior; y++) {
			Double x;
			if (retaVertical()) {
				x = this.pontos[0].getX();
			} else {
				x = (double) Math.round((y - calcularCoeficienteLinear()) / calcularCoeficienteAngular());
			}
			pontos.add(new Ponto(x, (double) y));
		}
		return pontos;
	}
	
	private Boolean retaVertical() {
		if (this.pontos[0].getX().equals(this.pontos[1].getX())) {
			return true;
		} else {
			return false;
		}
	}

	public Double calcularDistancia(FormaGeometrica forma) {
		// TODO Auto-generated method stub
		return null;
	}
}